<template>
  <Modal
    v-model="active"
    title="上传资源"
  >
    <Form
      ref="postfile"
      :label-width="90"
      :model="formData"
      :rules="rules"
    >
      <FormItem
        label="类型标签"
        prop="tag"
      >
        <Input
          v-model="formData.tag"
          placeholder="请输入文件类型标签"
        />
      </FormItem>
      <FormItem
        label="上传文件"
        prop="file"
      >
        <Upload
          ref="upload"
          v-model="formData.file"
          type="drag"
          :before-upload="beforeUpload"
          accept=".pdf, .aac, .mp3, "
          :format="['.pdf', '.aac', '.mp3']"
          :max-size="102400"
          :show-upload-list="false"
          action="javascript:;"
        >
          <div style="padding: 20px 0; background-color: #333;">
            <Icon
              type="ios-cloud-upload"
              size="52"
              style="color: #3399ff"
            />
            <p>
              点击选择文件或拖拽文件到此
            </p>
          </div>
        </Upload>
        <span style="margin-left: 10px">
          文件名称:
          <span v-if="formData.file === null">未选择文件</span>
          <span v-if="formData.file !== null">{{ formData.file.name }}</span>
        </span>
      </FormItem>
    </Form>
    <div slot="footer">
      <Button
        type="primary"
        :loading="loadingStatus"
        @click="handleUpload"
      >
        确定
      </Button>
    </div>
  </Modal>
</template>
<script lang="ts">
import { Component, Vue, Prop, Model, Watch } from 'vue-property-decorator'
import { CreateQueryParams } from '@nestjsx/crud-request'
import { DeepPartial } from 'ts-essentials'
import { Score, createScore, Track, createTrack } from '@/api/resources'
import { Form } from 'view-design'

@Component({
  name: 'PostModal',
  components: {}
})
export default class extends Vue {
  @Model('change', { type: Boolean }) readonly active!: boolean
  @Prop() userId!: number
  @Prop() songId!: number

  /* 上传过程中的加载状态控制 */
  private loadingStatus = false

  /* 表单绑定数据 */
  private formData: {tag: string; file: Blob | null} = {
    tag: '',
    file: null
  }

  /* 表单校验规则 */
  private get rules () {
    return {
      tag: [{ required: true, message: '请输入文件类型标签', trigger: 'emit' }],
      file: [
        { required: true, validator: this.validateUpload, trigger: 'change' }
      ]
    }
  }

  /* 上传文件校验器 */
  private validateUpload = (rule: any, value: any, callback: Function) => {
    if (!this.formData.file) {
      callback(new Error('请选择要上传的文件'))
    } else {
      callback()
    }
  }

  private get uploadData (): DeepPartial<Score> | DeepPartial<Track> {
    return {
      tag: this.formData.tag,
      file: this.formData.file!,
      relatedSong: { id: this.songId },
      uploadedByUser: { id: this.userId }
    }
  }

  private get params (): CreateQueryParams {
    return {
      join: [
        { field: 'relatedSong', select: ['id'] },
        { field: 'uploadedByUser', select: ['id'] }
      ]
    }
  }

  @Watch('active')
  private handleActiveStateChanged (active: boolean) {
    this.$emit('change', active)
  }

  private beforeUpload (file: Blob) {
    // 将获取到的文件流赋值给fromData
    this.formData.file = file
    // 选择文件后触发验证关闭错误提示
    // this.$refs.add.validate(() => {})
    return false
  }

  /* 执行表单验证 */
  private async verification () {
    const form = this.$refs.postfile as Form
    return new Promise<boolean>((resolve) => {
      form.validate((valid) => {
        resolve(valid)
      })
    })
  }

  /* 执行上传 */
  private async handleUpload () {
    this.loadingStatus = true
    const uploadSuccessEmit = () => {
      this.$emit('on-uploaded', true)
    }
    const doCreateScore = async () => {
      await createScore(this.uploadData as Partial<Score>, this.params)
        .then(() => {
          this.$emit('change', false)
          this.$Notice.success({
            title: '上传成功！',
            desc: '即将刷新页面',
            onClose: uploadSuccessEmit
          })
        })
        .finally(() => {
          this.loadingStatus = false
        })
    }
    const doCreateTrack = async () => {
      await createTrack(this.uploadData as Partial<Track>, this.params)
        .then(() => {
          this.$emit('change', false)
          this.$Notice.success({
            title: '上传成功！',
            desc: '即将刷新页面',
            onClose: uploadSuccessEmit
          })
        })
        .finally(() => {
          this.loadingStatus = false
        })
    }

    if (await this.verification() && this.formData.file) {
      switch (this.formData.file.type) {
        case 'application/pdf':
          await doCreateScore()
          break
        case 'audio/aac':
        case 'audio/x-aac':
        case 'audio/mp3':
        case 'audio/mpeg':
          await doCreateTrack()
          break
        default:
          this.$Message.error('不支持上传该文件，请重新选择文件')
      }
    }

    this.loadingStatus = false
  }
}
</script>
